﻿using System;

namespace HouseKeeperCore.Elemental
{
    /// <summary>
    ///  House keeper object that has an ID of long type and is disposable
    /// </summary>
    public class IdentifiableObject : IDisposable
    {
        #region Properties

        /// <summary>
        ///  The unique ID assigned to this entity
        /// </summary>
        public long Id { get; protected set; }

        /// <summary>
        ///  A flag indicating if the entity has been disposed of
        /// </summary>
        /// <remarks>
        ///  If a derived class wants to change it in its own disposing logic, it needs to make sure
        ///  before turning it to false it has properly disposed of all the resources it had taken including
        ///  those held by the base classes
        /// </remarks>
        protected bool Disposed
        {
            get
            {
                return (Id <= 0);
            }
            set
            {
                if (value == true)
                {
                    Id = 0;
                }
            }
        }


        #endregion

        #region Constructors

        /// <summary>
        ///  Instantiates an identifiable object with the specified ID
        /// </summary>
        /// <param name="id">The ID that uniquely identifies the object among its group</param>
        public IdentifiableObject(long id)
        {
            if (id <= 0)
            {
                throw new HouseKeeperException("Non-positive ID not allowed");
            }

            Id = id;
        }

        #endregion

        #region Methods

        #region Implementation of IDisposable

        /// <summary>
        ///  Allows caller to explicitly dispose of the instance
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion

        /// <summary>
        ///  Disposes of the instance
        /// </summary>
        /// <param name="disposing">Whether it's called from Dispose()</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!Disposed)
            {
                if (disposing)
                {
                    DisposeManaged();
                }

                DisposeUnmanaged();
                Disposed = true;
            }
        }

        /// <summary>
        ///  Disposes of managed resources
        /// </summary>
        protected virtual void DisposeManaged()
        {
        }

        /// <summary>
        ///  Disposes of unmanaged resources
        /// </summary>
        protected virtual void DisposeUnmanaged()
        {
        }

        #endregion
    }
}
